package cn.sdstudio.service.impl;

import cn.sdstudio.constants.SystemConstants;
import cn.sdstudio.config.CustomUserDetails;
import cn.sdstudio.config.MinioConfig;


import cn.sdstudio.entity.User;
import cn.sdstudio.exception.BusinessException;
import cn.sdstudio.mapper.UserMapper;
import cn.sdstudio.service.FileUploadService;
import cn.sdstudio.utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.minio.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.UUID;

/**
 * @author Zyq
 * @version 1.0
 * @date 2025/5/2 周五
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {

    private final MinioClient minioClient;

    private final MinioConfig minioConfig;

    private final UserMapper userMapper;


    /**
     * 上传到mino
     *
     * @param userId
     * @param file
     * @return
     */
    public String upload(Long userId, MultipartFile file) {
    if (userId == null) {
        throw new BusinessException(SystemConstants.EMPTY_ELEMENTS_CODE, SystemConstants.UPLOAD);
    }
    if (file.isEmpty()) {
        return SystemConstants.EMPTY_ELEMENTS;
    }
    String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();

    try {
        boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder()
                .bucket(minioConfig.getBucketName()).build());
        if (!bucketExists) {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(minioConfig.getBucketName()).build());
            // 只在新建桶时设置公开策略
            String policy = """
            {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "PublicReadGetObject",
                  "Effect": "Allow",
                  "Principal": {"AWS": ["*"]},
                  "Action": ["s3:GetObject"],
                  "Resource": ["arn:aws:s3:::%s/*"]
                }
              ]
            }
            """.formatted(minioConfig.getBucketName());
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .config(policy)
                    .build());
        }

        System.out.println("--------------------------------------------------------------");

        minioClient.putObject(PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build());
    } catch (Exception e) {
        log.error(e.getMessage(), e);
        throw new BusinessException("上传失败，请稍后重试");
    }
    return minioConfig.getEndpoint().replaceAll("/$", "") + "/" + minioConfig.getBucketName() + "/" + fileName;
}

    /**
     * 图片上传+数据库操作
     * <p>
     * 这里可以优化应该是先更新数据在上传
     *
     * @param
     * @param file
     * @return
     */
    @Override
    @Transactional
    public String uploadAvatar(MultipartFile file) {

        CustomUserDetails userDetails
                = SecurityUtils.getCurrentUser().orElseThrow(() -> new RuntimeException("未登录用户"));


        // 上传文件
        String url = upload(userDetails.getId(), file);

        log.info(url);
        // 更新数据库
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.<User>lambdaUpdate()
                .eq(User::getId, userDetails.getId()).set(User::getIcon, url);
        log.info(updateWrapper.toString());
        int updated = userMapper.update(updateWrapper);
        if (updated != 1) {
            // 数据库失败
            throw new RuntimeException("头像 URL 写入数据库失败");
        }
        return url;
    }
}
